package com.example.newjiesai.netty;

import com.example.newjiesai.jiesai.JiesaiDecoder;
import com.example.newjiesai.util.DateUtils;
import com.example.newjiesai.util.FormatUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.xml.bind.DatatypeConverter;

import static java.lang.System.out;
import static java.lang.System.setOut;


/**
    接收消息并根据消息所属协议解析并响应
 */
@Component

public class TcpInboundHandler extends ChannelInboundHandlerAdapter {

    private String imei;
    private static TcpInboundHandler tcpInboundHandler;
    //@Autowired                注入需要接口
    //private JiesaiDecoder jiesaiDecoder;


    //该注解会在项目启动的时候执行该方法，即spring容器初始化的时候执行，它与构造函数及@Autowired的执行顺序为：
    // 构造函数 >> @Autowired >> @PostConstruct
    @PostConstruct
    public void init(){
        tcpInboundHandler = this;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        out.println("channelActive");
        ctx.fireChannelActive();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf result = (ByteBuf) msg;
            byte[] resultByte = new byte[result.readableBytes()];
            // msg中存储的是ByteBuf类型的数据，把数据读取到byte[]中
            result.readBytes(resultByte);
            String resultHex = DatatypeConverter.printHexBinary(resultByte);        //将一个byte[]数组编码成一个16进制String类型，转义

            //int type = ProtocolSelector.identify(resultHex,new String(resultByte));     //协议识别
            //临时记录收到的数据
            System.out.println(DateUtils.getTime()+'\n'+"HEX :"+ resultHex);        //HEX表示传过来的16进制表示的字节流
            System.out.println("STR :"+new String(resultByte));                //STR表示这些16进制所表示的字节留所代表的字符串，找ASC码
            if(resultHex.equals("0D0A")) return;

            //----------------------------解析并返回应答消息------------------
            JiesaiDecoder jiesaiDecoder = new JiesaiDecoder();
            jiesaiDecoder.decode(new String(resultByte));

            this.imei = jiesaiDecoder.getImei();                      //设置保存Imei
            if(CurrentChannelService.getChannel(imei)==null){
                // tcpInboundHandler.deviceInfoService.s(imei,"1");
                CurrentChannelService.addChannel(imei, (SocketChannel) ctx.channel());
                System.out.println("a new connect come in: " + imei);
            }

            //resultBytes为00应该不写出
            byte[] responseBytes = jiesaiDecoder.getResponse();              //经过解析器，得到应答数组

            ByteBuf encoded = ctx.alloc().buffer(responseBytes.length);         //写出
            encoded.writeBytes(responseBytes);
            ctx.write(encoded);
            ctx.flush();

            //String t = DatatypeConverter.printHexBinary(responseBytes);
            String t = new String(responseBytes);
            System.out.println("应答消息:"+ t + "\n");
            System.out.println("----------------------");


            // 释放资源
            //encoded.release();
            result.release();


        }catch (Exception e)
        {
            e.printStackTrace();
        }
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        super.channelReadComplete(ctx);
        ctx.flush();
//        out.println("channelReadComplete");
        //ctx.close();

    }

    /**
     * 断开连接后移除Channel
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
        if(this.imei!=null){

            CurrentChannelService.removeChannel(imei);
            System.out.println(DateUtils.getTime());
            out.println("disconnect : " + imei+"\n"+"\n");

        }
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        Channel channel = ctx.channel();

        if(channel.isActive())ctx.close();
    }
}